/********************************************************************************
*                 Copyright (C) 2011 - Las Venturas Playground                  *
*                      http://iv-mp.nl | http://lvp-iv.com                      *
*                                                                               *
*    This program is free software: you can redistribute it and/or modify       *
*    it under the terms of the GNU General Public License as published by       *
*    the Free Software Foundation, either version 3 of the License, or          *
*    (at your option) any later version.                                        *
*                                                                               *
*    This program is distributed in the hope that it will be useful,            *
*    but WITHOUT ANY WARRANTY; without even the implied warranty of             *
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
*    GNU General Public License for more details.                               *
*                                                                               *
*    You should have received a copy of the GNU General Public License          *
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.      *
*                                                                               *
*********************************************************************************
*                                                                               *
*  Las Venturas Playground - Core/functions.nut                                 *
*                                                                               *
*  Global functions are located here.                                           *
*                                                                               *
********************************************************************************/

/**
 * This function returns a rotated string, used in sha1()
 * @author: Jones
 *
 * @param string val The value to rate?
 * @param string bits?
 * @return string The hashed string
 */
function rotateLeft(val, sbits)
{
    return (val << sbits) | (val >>> (0x20 - sbits));
}

/**
 * This function returns a sha1 hashed string.
 * @author: Jones
 *
 * @param string The string to hash
 * @return string The hashed string
 */
function sha1( string )
{
    local
        i, s,
        W = array(80, 0),
        H0 = 0x67452301,
        H1 = 0xEFCDAB89,
        H2 = 0x98BADCFE,
        H3 = 0x10325476,
        H4 = 0xC3D2E1F0,
        A, B, C, D, E,
        temp,
        len = string.len(),
         word_array = array(0);

    for(i = 0; i < len - 3; i += 4)
    {
        word_array.push(string[i] << 0x18 | string[i + 1] << 0x10 | string[i + 2] << 0x08 | string[i + 3]);
    }
 
    switch(len % 4)
    {
        case 0:
            i = 0x80000000;
        break;

        case 1:
            i = string[len - 1] << 0x18 | 0x0800000;
        break;
 
        case 2:
            i = string[len - 2] << 0x18 | string[len - 1] << 0x10 | 0x08000;
        break;
 
        case 3:
            i = string[len - 3] << 0x18 | string[len - 2] << 0x10 | string[len - 1] << 0x08 | 0x80;
        break;
    }
 
    word_array.push(i);
 
    while((word_array.len() % 0x10) != 0x0E)
        word_array.push(0);
 
    word_array.push(len >>> 0x1D);
    word_array.push((len << 0x03) & 0xFFFFFFFF);
 
 
    for(s = 0; s < word_array.len(); s += 0x10)
    {
 
        for(i = 0x00; i < 0x10; i++)
            W[i] = word_array[s + i];

        for(i = 0x10; i <= 0x4F; i++)
            W[i] = rotateLeft(W[i - 0x03] ^ W[i - 0x08] ^ W[i - 0x0E] ^ W[i - 0x10], 1);
 
        A = H0;
        B = H1;
        C = H2;
        D = H3;
        E = H4;
 
        for(i = 0x00; i <= 0x13; i++)
        {
            temp = (rotateLeft(A, 5) + ((B & C) | (~B & D)) + E + W[i] + 0x5A827999) & 0xFFFFFFFF;
            E = D;
            D = C;
            C = rotateLeft(B, 0x1E);
            B = A;
            A = temp;
        }
 
        for(i = 0x14; i <= 0x27; i++)
        {
            temp = (rotateLeft(A, 5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0xFFFFFFFF;
            E = D;
            D = C;
            C = rotateLeft(B, 0x1E);
            B = A;
            A = temp;
        }
 
        for(i = 0x28; i <= 0x3B; i++)
        {
            temp = (rotateLeft(A, 5) + ((B & C) | (B & D) | (C & D)) + E + W[i] + 0x8F1BBCDC) & 0xFFFFFFFF;
            E = D;
            D = C;
            C = rotateLeft(B, 0x1E);
            B = A;
            A = temp;
        }
 
        for(i = 0x3C; i <= 0x4F; i++)
        {
            temp = (rotateLeft(A, 5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0xFFFFFFFF;
            E = D;
            D = C;
            C = rotateLeft(B, 0x1E);
            B = A;
            A = temp;
        }
 
        H0 = (H0 + A) & 0xFFFFFFFF;
        H1 = (H1 + B) & 0xFFFFFFFF;
        H2 = (H2 + C) & 0xFFFFFFFF;
        H3 = (H3 + D) & 0xFFFFFFFF;
        H4 = (H4 + E) & 0xFFFFFFFF;
 
    }
 
    return format("%08x%08x%08x%08x%08x", H0, H1, H2, H3, H4);
}

/**
 * This function sends a pre formatted usage message
 * @author: Lithirm
 *
 * @param playerid The playerid to send the message to
 * @param Usage The message to send to the user.
 */
function sendPlayerUsageMessage( playerid, Usage )
{
    sendPlayerMessage (playerid, "* Usage: " + Usage, COLOR_WHITE, true);
}

/**
 * This function sends a pre formatted error message
 * @author: Lithirm
 *
 * @param playerid The playerid to send the message to
 * @param sError The message to send to the user.
 */
function sendPlayerErrorMessage( playerid, sError )
{
    sendPlayerMessage (playerid, "* Error: " + sError, COLOR_RED, true);
    return 1;
}

/**
 * This function returns a random integer between the specified minimum and maximum value.
 * @author: Lithirm
 *
 * @param min The minimum number, the default value is 0
 * @param max The maximum number, the default value is RAND_MAX
 */
function random( min = 0, max = RAND_MAX)
{
   // srand(getTickCount() * rand());
   srand((getTickCount() << 16) | (rand() & 0xFFFF)); // I like this better  -Pugwipe
   
   return (rand() % ((max + 1) - min)) + min;
}

/*
 * Function: arrayShuffle ()
 * Randomizes the order of an array.
 * @author  Pugwipe <pugwipe@gmail.com>
 *
 * @param array  The array that needs to be shuffled, taken by reference
 */ 
function arrayShuffle (array)
{
    local len = array.len ();
    for (local i = 0; i < len; i++) 
    {
        local k = random (0, len - 1);
        local tmp = array[i];
        array[i] = array[k];
        array[k] = tmp;
    }
}

/**
 * This function sends the correct error message to the user,
 * uses output from the getPlayerFromInput function. 
 * @author: Pugwipe <pugwipe@gmail.com>
 *
 * @param playerid The playerid to send the error message to
 * @param iError The error id, -1 is no matching players, -2 is too many.
 */
function sendInvalidPlayerMessage (playerid, Error)
{
    if (Error == -1) 
    {
        sendPlayerErrorMessage (playerid, "no matching players found.");
    }
    
    else if (Error == -2) 
    {
        sendPlayerErrorMessage (playerid, "too many matching players found.");
    }
}

/**
 * This function checks whether a certain string is numeric or not.
 *
 * @param string The string to check.
 * @param false if it's not numeric, true if it is.
 */
function isNumeric (string)
{
   try
   {
      string.tointeger ();
   }
   catch (string)
   {
      return false;
   }
   
   return true;
}

/**
 * This function checks whether a certain string is numeric or not.
 * @author: Pyrokid, edited by Matthias
 *
 * @param player The string to search the player in.
 * @return Either the playerid if somebody was found -2 if there were too many matches, -1 if there were none.
 */
function getPlayerFromInput (player)
{    
    if (isNumeric (player) && isPlayerConnected (player.tointeger ())) 
    {
        return player.tointeger ();
    }

    local Matches = 0;
    local TargetID = -1;
    player = player.tolower ();
        
    for (local i = 0, slots = getPlayerSlots (); i < slots; i++) 
    {
        if (isPlayerConnected (i)) 
        {
            local name = getPlayerName (i).tolower ();
            if (name == player) return i;
            
            if (name.find (player) != null)
            {
                Matches++;
                TargetID = i;
                
                if (Matches > 1)
                {
                    TargetID = -2;
                }
            }
        }
    }
    return TargetID;
}

/**
 * This function converts an given input of a weaponname (of a part of it)
 * to an ID.
 * @author: Xanland, copied from getVehicleModelIDFromName and made it
 *                   suitable for weapons.
 *
 * @param weaponName (Part of) a weaponname.
 * @return weaponID The weaponID of the given name of the vehicle.
 */
function getWeaponIDFromName (weaponName)
{
    if (isNumeric (weaponName))
    {
        return weaponName.tointeger ();
    }    
    
    for (local weaponID = 0; weaponID < weaponNames.len (); weaponID++)
    {
        if (weaponID == 6 || weaponID == 8) continue;
        
        if (weaponNames[weaponID].tolower ().find (weaponName.tolower ()) != null)
        {
            return weaponID;
        }
    }
    return -1;
}

/**
 * This function returns the value from the key from an xml file
 * @author: Matthias <matthias@sa-mp.nl>
 *
 * @param XmlFile A reference to the xml file
 * @param Key The key to search the value from
 * @return The content of that key
 */

function getXmlValue(XmlFile, Key)
{
	// Find the node
	XmlFile.nodeFind (Key);
	
	// Get the node content
    local Value = XmlFile.nodeContent ();
	
	// Set the node pointer back to the root of the file
	XmlFile.nodeRoot();
	
	// Return the value
	return Value;
}

// Add the event to freeze the player.
addEvent("freezePlayer", togglePlayerFrozen);

// We include the functions of the handlers here:

dofile("./scripts/Handlers/Account/functions.nut");
dofile("./scripts/Handlers/Vehicle/functions.nut");
